package com.zhangfei.plus.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@RestController
public class MyLoadBalanceController {


    @Autowired
    private DiscoveryClient discoveryClient;

    @RequestMapping(value = "/allService", method = RequestMethod.GET)
    public String getAllService() {
        // 获取服务的实例
        List<String> services = discoveryClient.getServices();
        return services.toString();
    }


    @RequestMapping(value = "/allInstance", method = RequestMethod.GET)
    public String getAllInstance() {
        // 获取服务的实例
        List<ServiceInstance> instances = discoveryClient.getInstances("nacos-discovery-provider");
        return instances.get(0).getUri().toString();
    }


    @Resource
    private RestTemplate restTemplate;


    @RequestMapping(value = "/myLoadBalance", method = RequestMethod.GET)
    public String myLoadBalance() {
        //模拟ribbon实现,自定义负载均衡策略
        String url = getUri("mall-nacos-discovery-provider");
        return restTemplate.getForObject(url + "/echo/myLoadBalance", String.class);
    }

    public String getUri(String serviceName) {
        // 获取服务的实例
        List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
        if (instances.isEmpty()) {
            return null;
        }
        int serviceSize = instances.size();
        //轮询
        int indexServer = incrementAndGetModulo(serviceSize);
        return instances.get(indexServer).getUri().toString();
    }


    private AtomicInteger nextIndex = new AtomicInteger(0);

    private int incrementAndGetModulo(int modulo) {
        for (; ; ) {
            int current = nextIndex.get();
            int next = (current + 1) % modulo;
            if (nextIndex.compareAndSet(current, next) && current < modulo) {
                return current;
            }
        }
    }


}
